import Request from 'luch-request';
import { isApi, exchange } from './utils'
import { deepmerge } from "deepmerge-ts";
// http实例
export const http = new Request();


/**
 * 配置初始化
 * @param options 
 */
export const init = function(options){
  // 请求拦截
  if(options?.request){
    let req = options.request
    request(req, config=>Promise.reject(config))
    delete options.request
  }
  // 响应拦截
  if(options?.response){
    response(options.response, config=>Promise.reject(config))
    delete options.response
  }
  
  setConfig(options)
}

/**
 * 修改配置
 * @param options 
 */
export function setConfig(options):void{
  if(options){
    if(options.constructor?.name!='Object') throw new Error('配置信息有误, 请检查相应配置')
    http.setConfig((config)=>deepmerge(config, options))
  }
}

// 请求拦截
export const request = (fulfilled, rejected)=>{
  http.interceptors.request.use(fulfilled, rejected)
}
// 响应拦截
export const response = (fulfilled, rejected)=>{
  http.interceptors.response.use(fulfilled, rejected)
}


/**
 * 批量生产api
 * @param apis 
 */
export const api = function(apis:any){
  if(!apis) throw new Error('api配置不能为空')
  return resolve(apis)
}

/**
 * api加工
 * @param apis 
 * @param model 
 */
function resolve(apis:any, model:string[]=[]){
  let res:any = {}
  for (const key in apis) {

    if(apis[key]?.constructor?.name!='String'){
      let api = apis[key]
      if(api?.constructor?.name=='Array') api = exchange(api)
      if(key=='*') {
        res = resolve(api,model)
      }else{
        res[key] = resolve(api,model.concat(key))
      }
    }else{
      let {name, method} = isApi(key,apis[key])
      res[name] = newRequest(method, model.concat(apis[key]).join('/')) 
    }
  }
  return res
}

/**
 * 上传类型
 */
type uploadParams = {
  files?: any[],
  filePath?:string
}

/**
 * 生成请求
 * @param method 
 * @param value 
 */
function newRequest(method:string='g', value:string){
  switch (method) {
    case 'g': // get
      return (params, config={}) => http.get(value, {params, ...config})
      break;
    case 'p': // post
      return (params, config={}) => http.post(value, params, config)
      break;
    case 'u': // upload
      return (params:uploadParams, config={}) => http.upload(value,{...params, ...config})
      break;
    case 'd': // download
      return (params, config={}) => http.download(value,{...params, ...config})
      break;
    default:  // get
      return (params, config={}) => http.get(value, {params, ...config})
      break;
  }
}